package org.softmed.rest.editor;

import java.awt.Color;
import java.awt.Dimension;
import java.util.List;

import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;

import org.softmed.rest.admin.ModuleManager;
import org.softmed.rest.admin.DetailChooser.DetailLevel;
import org.softmed.rest.admin.config.ConfigurationActionPanel;
import org.softmed.rest.admin.config.ConfigurationEditor;
import org.softmed.rest.admin.file.CustomFileNode;
import org.softmed.rest.admin.file.DirectoryNode;
import org.softmed.rest.admin.file.FileBrowser;
import org.softmed.rest.admin.file.FileManager;
import org.softmed.rest.admin.file.OpenFileListener;
import org.softmed.rest.admin.file.SelectionListener;
import org.softmed.rest.admin.httpMethods.HTTPMethodEditor;
import org.softmed.rest.admin.interfaces.CloseListener;
import org.softmed.rest.admin.interfaces.FileHandler;
import org.softmed.rest.admin.mediaType.MediaTypeEditor;
import org.softmed.rest.admin.module.ModuleEditor;
import org.softmed.rest.admin.module.ModuleHeader;
import org.softmed.rest.admin.module.ModuleResourceManager;
import org.softmed.rest.admin.resource.ResourceEditor;
import org.softmed.rest.admin.resource.ResourceHeader;
import org.softmed.rest.admin.resource.ResourceMethodsManager;

import restlet.description.convert.RESTConfigurationDescription;
import restlet.description.convert.RESTModuleDescription;


public class RESTEditor extends Editor implements SelectionListener,
		FileHandler, OpenFileListener, CloseListener {

	FileManager fileManager;
	RESTConfigurationManager configurationManager = new RESTConfigurationManager();
	FileBrowser fileBrowser;
	DevToolBar bar;
	ConfigurationEditor cfgEditor;
	JScrollPane scroll;
	JPanel scrollContent = new JPanel();

	ModuleManagerGUI moduleManagerGUI;
	boolean closed = true;

	public void setup() {

		closed = true;

		bar = new DevToolBar(toolbar, this);
		setJMenuBar(bar);

		scroll = new JScrollPane(scrollContent);

		scroll.setPreferredSize(new Dimension(560, 700));
		scroll.setMaximumSize(new Dimension(560, 700));
		scroll.setMinimumSize(new Dimension(560, 700));
		scroll
				.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
		// scroll
		// .setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
		center.add(scroll);

		moduleManagerGUI = new ModuleManagerGUI(this);
		right.add(moduleManagerGUI);
		right.add(Box.createVerticalGlue());

		fileBrowser = new FileBrowser();
		left.add(fileBrowser);
		left.revalidate();
		fileBrowser.setSelectionListener(this);
		fileBrowser.setOpenFileListener(this);

	}

	public FileManager getFileManager() {
		return fileManager;
	}

	public void setFileManager(FileManager fileManager) {
		this.fileManager = fileManager;
		fileBrowser.setFileManager(fileManager);
		configurationManager.setFileManager(fileManager);
	}

	protected void sendValidationErrorPopup(String text) {
		sendErrorPopup("Validation Error", text);

	}

	protected void sendFileIOErrorPopup(String text) {
		sendErrorPopup("File I/O Error", text);

	}

	protected void sendErrorPopup(String title, String text) {
		JOptionPane.showConfirmDialog(this, text, title,
				JOptionPane.DEFAULT_OPTION, JOptionPane.ERROR_MESSAGE);
	}

	public String createFileWithPopup() {
		return fileBrowser.createFileWithPopup();
	}

	public void setConfigurationMode() {
		if (!closed)
			throw new RuntimeException(
					"Can't changed modes unless editor is closed ! ");

		closed = false;
		configurationActionPanel.activate();
		moduleManager.close();
		moduleManagerGUI.setConfigurationMode();
		loadConfiguration(new RESTConfigurationDescription());
	}

	public void setModuleMode() {
		if (!closed)
			throw new RuntimeException(
					"Can't changed modes unless editor is closed ! ");

		closed = false;
		configurationActionPanel.deactivate();
		moduleManager.close();
		moduleManagerGUI.setModuleMode();
	}

	@Override
	public void close() {
		// TODO warn about unsaved changes

		moduleManagerGUI.close();
		configurationActionPanel.deactivate();
		// configurationActionPanel.activate();
		moduleManager.close();
		closed = true;

	}

	public void loadConfiguration(RESTConfigurationDescription description) {
		try {
			closed = false;
			loadAllModules(description);
			cfgEditor.setConfigurationDescription(description);
		} catch (Throwable t) {
			t.printStackTrace();
			sendFileIOErrorPopup("Error Loading Configuration");
		}
	}

	private void loadAllModules(RESTConfigurationDescription description)
			throws Throwable {
		List<String> paths = description.getModuleConfigurationFiles();
		for (String path : paths) {
			RESTModuleDescription module = configurationManager
					.loadModule(path);
			module.setPath(path);
			description.getModuleDescriptions().add(module);
		}

	}

	public void saveAllConfiguration(String path) {
		if (saveConfigurationOnly(path))
			saveAllModules();
	}

	public void saveAllModules() {
		try {
			cfgEditor.validateData();
		} catch (Throwable t) {
			t.printStackTrace();
			sendValidationErrorPopup(t.getMessage());
			return;
		}

		try {
			// apply pendent changes
			RESTConfigurationDescription config = cfgEditor
					.getConfigurationDescription();
			List<RESTModuleDescription> modules = config
					.getModuleDescriptions();
			for (RESTModuleDescription moduleDescription : modules) {
				configurationManager.saveModule(moduleDescription);
			}
		} catch (Throwable t) {
			t.printStackTrace();
			sendFileIOErrorPopup("Error saving Modules");
		}

	}

	public void removeAllModules() {
		int duh = JOptionPane.showConfirmDialog(this,
				"Are you sure you want to remove all modules ?", "Warning",
				JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE);

		if (duh == JOptionPane.YES_OPTION) {
			moduleManager.close();
			// fileBrowser.deleteSelection();
		}

		this.invalidate();
		this.repaint();

	}

	public boolean saveConfigurationOnly(String path) {
		try {
			cfgEditor.validateData();
		} catch (Throwable t) {
			t.printStackTrace();
			sendValidationErrorPopup(t.getMessage());
			return false;
		}
		try {
			configurationManager.saveConfiguration(cfgEditor
					.getConfigurationDescription(), path);
		} catch (Throwable t) {
			t.printStackTrace();
			sendFileIOErrorPopup("Error saving configuration file");
			return false;
		}

		return true;
	}

	@Override
	public void selectionChanged(CustomFileNode node) {
		String name = fileBrowser.getCurrentSelectedNodeName();
		boolean directory = false;
		if (node instanceof DirectoryNode)
			directory = true;

	}

	@Override
	public String retrieveFilePath() {
		return fileBrowser.getCurrentSelectedNodePath();
	}

	@Override
	public void fileOpened(String filePath) {
		// TODO if file is .groovy, open editor, if it is .xml try to open it
		// with editor configurator
		// and determine wether it is a module or a configuration and change the
		// Editor accordingly
		// anything else, throw a pop up saying you can't open the file
		if (filePath.endsWith(".xml")) {
			if (!closed)
				sendErrorPopup(
						"Error",
						"Can't open another file while editing.\n Please save and close current file first.");

			close();
			try {
				RESTConfigurationDescription cfg = configurationManager
						.loadConfiguration(filePath);
				setConfigurationMode();
				System.out.println("configuration loaded");
				loadConfiguration(cfg);
				configurationActionPanel.pathField.setText(filePath);
				// TODO update Editor
			} catch (Throwable t) {

				try {
					configurationManager.loadModule(filePath);
					setModuleMode();
					System.out.println("module loaded");
					// TODO update Editor
				} catch (Throwable t2) {
					throw new RuntimeException("Unresolved XML file !!!");
				}
			}

		} else if (filePath.endsWith(".groovy")) {
			// TODO open groovy editor
			throw new RuntimeException("Groovy Editor not implemented yet !!!");
		}

	}

}
